//
// Created by DELL on 2022/4/20.
//

#pragma once

#include "../Utils.h"
#include "../VulkanDefine.h"

BEGIN_NS_VULKAN

struct PipelineConfigInfo
{
    PipelineConfigInfo() = default;
    PipelineConfigInfo(const PipelineConfigInfo&) = delete;
    PipelineConfigInfo& operator=(const PipelineConfigInfo&) = delete;

    std::vector<VkVertexInputBindingDescription> vertexBindings;
    std::vector<VkVertexInputAttributeDescription> vertexAttributes;
    std::vector<VkDescriptorSetLayout> setLayouts;
    VkPipelineInputAssemblyStateCreateInfo inputAssemblyInfo{};
    VkPipelineRasterizationStateCreateInfo rasterizationInfo{};
    VkPipelineMultisampleStateCreateInfo multisampleInfo{};
    VkPipelineColorBlendAttachmentState colorBlendAttachment{};
    VkPipelineDepthStencilStateCreateInfo depthStencilInfo{};
    std::vector<VkDynamicState> dynamicStateEnables;
    VkRenderPass renderPass{};
    uint32_t subpass{};
};

class Pipeline
{
public:
    ~Pipeline();
    Pipeline(const Pipeline&) = delete;
    Pipeline operator=(const Pipeline&) = delete;

    static PipelineRef create(DeviceRef& device, const ShaderRef& shader, const PipelineConfigInfo& configInfo);

    static void defaultPipelineConfigInfo(PipelineConfigInfo& info);

    VkPipeline getPipeline() { return this->graphicsPipeline; }
    VkPipelineLayout getPipelineLayout() { return this->pipelineLayout; }

private:
    explicit Pipeline(DeviceRef device);

    void init(const ShaderRef& shader, const PipelineConfigInfo& configInfo);
    void createShaderModule(const std::vector<uint32_t>& code, VkShaderModule* shaderModule);

    DeviceRef device;
    VkPipeline graphicsPipeline{};
    VkPipelineLayout pipelineLayout{};
};

END_NS_VULKAN